package org.gp.core.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.gp.core.entity.*;
import org.gp.core.entity.enums.MessageEnum;
import org.gp.core.service.IWechatService;
import org.gp.core.utils.CheckUtils;
import org.gp.core.utils.MessageUtil;
import org.gp.core.utils.OkHttpUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by luoliang on 2017/1/28.
 */
@Slf4j
@Service
public class WechatServiceImpl implements IWechatService {
    @Value("${wechat.token}")
    private String token;
    @Value("${wechat.appID}")
    private String appID;
    @Value("${wechat.appsecret}")
    private String appsecret;
    @Value("${wechat.access_token_url}")
    private String ACCESS_TOKEN_URL;
    @Value("${wechat.menu_create_url}")
    private String MENU_CREATE_URL;
    @Value("${wechat.oauth_access_token_url}")
    private String OAUTH_ACCESS_TOKEN_URL;
    @Value("${wechat.wx_userinfo_url}")
    private String WX_USERINFO_URL;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * signature 微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
     * timestamp 时间戳
     * nonce     随机数
     * echostr   随机字符串
     */
    @Override
    public String checkSignature(CheckModel checkModel) {
        String signature = checkModel.getSignature();
        String timestamp = checkModel.getTimestamp();
        String nonce = checkModel.getNonce();
        String echostr = checkModel.getEchostr();
        String[] str = new String[]{token, timestamp, nonce};

        //字典排序
        Arrays.sort(str);

        //拼接三个字符串
        StringBuilder stringBuilder = new StringBuilder();
        for (String s : str) {
            stringBuilder.append(s);
        }

        //进行sha1加密
        String temp = CheckUtils.getSha1(stringBuilder.toString());

        if (temp.equals(signature))
            return echostr;
        else
            return "error";
    }

    @Override
    public AccessToken getAccessToken() {
        String res = "";

        res = stringRedisTemplate.opsForValue().get("ACCESS_TOKEN");
        log.info("从缓存中读取到的AccessToken为：{}", res);

        if (res == null) {
            log.info("AccessToken的redis缓存不存在，重新向微信服务器请求，并存储到redis");
            String requestUrl = ACCESS_TOKEN_URL.replaceAll("APPID", appID).replace("APPSECRET", appsecret);

            try {
                res = OkHttpUtil.get(requestUrl);
            } catch (IOException e) {
                log.error("获取access_token失败：{}", e);
            }

            stringRedisTemplate.opsForValue().set("ACCESS_TOKEN", res, 7140, TimeUnit.SECONDS);
        }

        return JSON.parseObject(res, AccessToken.class);
    }

    /**
     * post请求创建微信菜单
     *
     * @param menu
     * @return
     */
    @Override
    public String createMenu(Menu menu) {
        AccessToken accessToken = null;
        String result = "";
        try {
            accessToken = getAccessToken();

            String requestUrl = MENU_CREATE_URL.replace("ACCESS_TOKEN", accessToken.getAccess_token());

            result = OkHttpUtil.post(requestUrl, JSON.toJSONString(menu));
        } catch (IOException e) {
            log.error("创建菜单失败：", e);
        }

        return result;
    }

    /**
     * 根据网页参数code请求OpenId
     *
     * @param code
     * @return
     */
    @Override
    public OpenId getOpenId(String code) {
        String requestUrl = OAUTH_ACCESS_TOKEN_URL.replace("APPID", appID).replace("SECRET", appsecret).replace("CODE", code);

        String res = "";
        try {
            res = OkHttpUtil.get(requestUrl);
            log.info("请求OpenId结果为：{}", res);
        } catch (IOException e) {
            log.error("请求OpenId失败：", e);
        }

        return JSON.parseObject(res, OpenId.class);
    }

    /**
     * 根据openid和accesstoken请求用户信息，此accesstoken是网页开发的，和全局accesstoken不同
     *
     * @param openIdStr
     * @param accessToken
     */
    @Override
    public WxUserInfo getUserInfo(String openIdStr, String accessToken) {
        String requestUrl = WX_USERINFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openIdStr);

        String res = "";
        try {
            res = OkHttpUtil.get(requestUrl);
            log.info("请求用户信息为：{}", res);
        } catch (IOException e) {
            log.error("请求用户信息失败：", e);
        }

        return JSON.parseObject(res, WxUserInfo.class);
    }

    /**
     * 根据用户发送的消息生成回复消息
     *
     * @param map
     * @return
     */
    @Override
    public String initMessage(Map<String, String> map) {
        String FromUserName = map.get("FromUserName");
        String ToUserName = map.get("ToUserName");
        String MsgType = map.get("MsgType");
        String Content = map.get("Content");
        String message = "";

        if (MessageEnum.MESSAGE_TEXT.getDesc().equals(MsgType)) {
            if (Content.contains("XXX")) {

            }
        } else if (MessageEnum.MESSAGE_EVENT.getDesc().equals(MsgType)) {
            String eventType = map.get("Event");
            if (MessageEnum.MESSAGE_SUBSCRIBE.getDesc().equals(eventType)) {
                message = MessageUtil.initText(ToUserName, FromUserName,
                        MessageUtil.menuText());
            }
        }

        return message;
    }
}
